<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/7/31
 * Time: 22:53
 */

namespace app\api\service;

use app\api\model\Product;
use app\api\model\OrderProduct;
use app\api\model\UserAddress;
use app\lib\exception\ProductException;
use app\lib\exception\UserException;
use app\api\model\Order as OrderModel;
use think\Db;

class Order
{
    protected $uid;
    protected $products;//数据库中的商品信息
    protected $orderProducts;//定单表中的商品信息
    //定义一个初始化值的方法
    //static 方法中不能有$this
    public function place($uid, $orderProducts)
    {
        $this->uid = $uid;
        $this->orderProducts = $orderProducts;
        $this->products = $this -> getProductsByOrder($orderProducts);
        $status = $this -> getOrderStatus();
        if(!$status['pass']){
            $staus['order_id'] = -1;
            return $status;
        }
    //创建定单快照
        $orderSnap = $this -> snapOrder($status);
        $order = $this -> createOrder($orderSnap);
        $order['pass'] = true;
        return $order;
    }
    //创建定单的方法
    public function createOrder($snap)
    {
        Db::startTrans();
        try{
            $orderNum = $this -> makeOrderNo();
            $order = new OrderModel();
            $order -> user_id = $this -> uid;
            $order -> order_no = $orderNum;
            $order -> total_price = $snap['orderPrice'];
            $order -> total_count = $snap['totalCount'];
            $order -> snap_img = $snap['snapImg'];
            $order -> snap_name = $snap['snapName'];
            $order -> snap_address = $snap['snapAddress'];
            $order -> snap_items = json_encode($snap['pStatus']);
            $order -> save();

            $orderId = $order -> id;
            $create_time = $order -> create_time;
            foreach ($this -> orderProducts as &$val)
            {
                $val['order_id'] = $orderId;
            }

            $productOrder = new OrderProduct();
            $productOrder -> saveAll($this -> orderProducts);
        }catch (\Exception $ex) {
            throw $ex;
        }
        Db::commit();
        return [
            'order_no' => $orderNum,
            'order_id' => $orderId,
            'create_time' => $create_time,
        ];
    }
    //使用随机数生成一个定单号
    public static function makeOrderNo()
    {
        $yCode = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'];
        $orderNo = $yCode[intval(date('Y')-2017)].strtoupper(dechex(date('m'))).date('d').substr(time(),-5).substr(microtime(), 2, 5).sprintf('%02d', rand(0,99));
        return $orderNo;
    }
    //获取定单快照的数组
    private function snapOrder($status)
    {
        $snap = [
            'orderPrice' => 0,
            'totalCount' => 0,
            'pStatus' => [],
            'snapAddress' => '',
            'snapName' => '',
            'snapImg' => '',
        ];
        $snap['orderPrice'] = $status['orderPrice'];
        $snap['totalCount'] = $status['totalCount'];
        $snap['pStatus'] = $status['pStatusArray'];
        $snap['snapAddress'] = json_encode($this -> getUserAddress());
        $snap['snapName'] = $this -> products[0]['name'];
        $snap['snapImg'] = $this -> products[0]['main_img_url'];
        if(count($this -> products) > 1) $snap['snapName'] .= '等';
        return $snap;
    }
    //定义一个获取定单快照地址的方法
    private function getUserAddress()
    {
        $userAddress = UserAddress::where(['user_id' => $this -> uid]) -> find();
        if(!$userAddress) {
            throw new UserException(['msg' => '地址不存在！', 'errorCode' => 60000    ]);
        }
        return $userAddress;
    }
    //定义一个用在Service里的Pay类的方法，以便代码的复用
    public function checkOrderStock($orderId)
    {
        $oProducts = OrderProduct::where(['order_id',$orderId]) -> select();
        $this -> oProducts = $oProducts;

        $this -> products = $this -> getProductsByOrder($oProducts);
        $status = $this -> getOrderStatus();
        return $status;
    }
    //把所有商品的信息存诸在一个数组中
    private function getOrderStatus()
    {
        $status = [
            'pass' => true,
            'orderPrice' => 0,
            'totalCount' => 0,
            'pStatusArray' => [],
        ];
        foreach($this -> orderProducts as $orderProduct) {
            $pStatus = $this -> getProductStatus($orderProduct['product_id'], $orderProduct['count'], $this -> products);
            if(!$pStatus['haveStock']) $status['pass'] = false;
            $status['orderPrice'] += $pStatus['totalPrice'];
            $status['totalCount'] += $pStatus['count'];
            array_push($status['pStatusArray'], $pStatus);
        }
        return $status;
    }
    //定义一个嵌套的方法来获取商品的具体信息
    private function getProductStatus($oid, $ocount, $products)
    {
        $pindex = -1;
        $pStatus = [
            'id' => null,
            'haveStock' => 0,
            'count' => 0,
            'name' => '',
            'totalPrice' => 0,
        ];
        for($i = 0; $i < count($products); $i++)
        {
            if($oid == $products[$i]['id']) {
                $pindex = $i;
            }
        }
        //如果商品不存在
        if($pindex == -1) throw new ProductException(['msg' => '商品信息不存在!']);
        $product = $products[$pindex];
        //把商品信息存到数组
        $pStatus['id'] = $product['id'];
        $pStatus['count'] = $ocount;
        $pStatus['name'] = $product['name'];
        $pStatus['totalPrice'] = $product['price'] * $ocount;
        if($product['stock'] - $ocount >= 0) {
            $pStatus['haveStock'] = true;
        }
        return $pStatus;
    }
    //通过order来获取所有选中的商品
    protected function getProductsByOrder($orderProducts)
    {
        $idList = [];
        //获取所有商品的id
        foreach ($orderProducts as $value)
        {
            array_push($idList, $value['product_id']);
        }
        return $result = Product::all($idList);
    }
}